/**
 * Copyright (c) Software Institude of PKU
 * All rights reserved. 
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 */
package edu.pku.sei.transformation.editor.model.variable;

// imports:
import java.util.ArrayList;

import org.w3c.dom.Element;

import edu.pku.sei.gefcommon.descriptor.annotation.MethodProperty;
import edu.pku.sei.modeler.model.core.MetaClass;
import edu.pku.sei.modeler.model.core.MetaClassifier;
import edu.pku.sei.modeler.model.core.MetaGeneralization;
import edu.pku.sei.modeler.model.core.MetaModelElement;
import edu.pku.sei.modeler.model.core.MetaReference;
import edu.pku.sei.modeler.model.xml.XMLUtility;
import edu.pku.sei.transformation.editor.model.ModelPackage;
import edu.pku.sei.transformation.editor.model.pattern.ILinkTemplate;
import edu.pku.sei.transformation.editor.model.pattern.INodeTemplate;
import edu.pku.sei.transformation.editor.model.pattern.Pattern;

/**
 * @generated
 * 
 */
public class ConnectionVariable extends Variable implements ILinkTemplate {
	protected ObjectVariable source;
	protected ObjectVariable target;
	private Pattern pattern;

	private String sourceRole;
	private String targetRole;

	@Override
	public Object[] getTypes() {
		ArrayList result = new ArrayList();
		if (this.source != null) {
			MetaModelElement element = this.source.getType();
			if (element instanceof MetaClass) {
				MetaClass cls = (MetaClass) element;
				for (Object object : cls.getAllReferences()) {
					if (object instanceof MetaReference
							&& (((MetaReference) object).getType() == (MetaClassifier) target
									.getType() || isSuperClass(
									((MetaReference) object).getType(),
									(MetaClassifier) target.getType()))) {
						result.add(object);
					}
				}
			}
		}
		return result.toArray();
	}

	private boolean isSuperClass(MetaClassifier superCls, MetaClassifier cls) {
		for (Object obj : cls.getGenerals()) {
			if (((MetaGeneralization) obj).getGeneral() == superCls) {
				return true;
			} else {
				isSuperClass(superCls, ((MetaGeneralization) obj).getGeneral());
			}
		}
		return false;
	}

	@Override
	public void setType(MetaModelElement modelType) {
		if (modelType != null) {
			MetaReference ref = (MetaReference) modelType;
			this.setTargetRole(ref.getName());
			if (ref.getOpposite() != null)
				this.setSourceRole(ref.getOpposite().getName());

		}
		super.setType(modelType);
	}

	@MethodProperty(name = "source role", catalog = "Connection", id = ModelPackage.CONNECTION_VARIABLE_SOURCEROLE, setter = "setSourceRole")
	public String getSourceRole() {
		return sourceRole;
	}

	public void setSourceRole(String sourceRole) {
		if (getType() == null) {
			String oldValue = this.sourceRole;
			if (oldValue == null || !oldValue.equals(sourceRole)) {
				this.sourceRole = sourceRole;
				this.firePropertyChange(
						ModelPackage.CONNECTION_VARIABLE_SOURCEROLE, oldValue,
						sourceRole);
			}
		}
	}

	@MethodProperty(name = "taget role", catalog = "Connection", id = ModelPackage.CONNECTION_VARIABLE_TARGETROLE, setter = "setTargetRole")
	public String getTargetRole() {
		return targetRole;
	}

	public void setTargetRole(String targetRole) {
		if (getType() == null) {
			String oldValue = this.targetRole;
			if (oldValue == null || !oldValue.equals(targetRole)) {
				this.targetRole = targetRole;
				firePropertyChange(ModelPackage.CONNECTION_VARIABLE_TARGETROLE,
						oldValue, targetRole);
			}
		}
	}

	public ObjectVariable getSource() {
		return source;
	}

	public void setSource(INodeTemplate source) {
		this.source = (ObjectVariable) source;
	}

	public ObjectVariable getTarget() {
		return target;
	}

	public void setTarget(INodeTemplate target) {
		this.target = (ObjectVariable) target;
	}

	@Override
	public Pattern getPattern() {
		if (pattern == null && getContainer() != null
				&& getContainer() instanceof Pattern) {
			pattern = (Pattern) getContainer();
		}
		return pattern;
	}

	@Override
	public void setPattern(Pattern pattern) {
		this.pattern = pattern;
	}

	public void serialize(Element root) {
		super.serialize(root);
		XMLUtility.xmlInstance.serializeAttribute(root,
				ModelPackage.CONNECTION_VARIABLE_SOURCEROLE, this.sourceRole);
		XMLUtility.xmlInstance.serializeAttribute(root,
				ModelPackage.CONNECTION_VARIABLE_TARGETROLE, this.targetRole);

		XMLUtility.xmlInstance.serializeNodeNotContain(root,
				ModelPackage.LINK_TEMPLATE_SOURCE, source);
		XMLUtility.xmlInstance.serializeNodeNotContain(root,
				ModelPackage.LINK_TEMPLATE_TARGET, target);
		XMLUtility.xmlInstance.serializeNodeNotContain(root,
				ModelPackage.PATTERN_TEMPLATE_PATTERN, this.pattern);

	}

	public void deSerialize(Element root) {
		super.deSerialize(root);
		this.sourceRole = XMLUtility.xmlInstance.deSerializeString(root,
				ModelPackage.CONNECTION_VARIABLE_SOURCEROLE);
		this.targetRole = XMLUtility.xmlInstance.deSerializeString(root,
				ModelPackage.CONNECTION_VARIABLE_TARGETROLE);

		this.source = (ObjectVariable) XMLUtility.xmlInstance
				.deSerializeNodeNotContain(root,
						ModelPackage.LINK_TEMPLATE_SOURCE, this);
		this.target = (ObjectVariable) XMLUtility.xmlInstance
				.deSerializeNodeNotContain(root,
						ModelPackage.LINK_TEMPLATE_TARGET, this);
		this.pattern = (Pattern) XMLUtility.xmlInstance
				.deSerializeNodeNotContain(root,
						ModelPackage.PATTERN_TEMPLATE_PATTERN, this);

	}

	public void dynamicSet(String featureID, Object value) {
		if (featureID == null || "".equals(featureID)) {
			return;
		} else if (ModelPackage.PATTERN_TEMPLATE_PATTERN.equals(featureID)) {
			this.pattern = (Pattern) value;
		} else if (ModelPackage.LINK_TEMPLATE_SOURCE.equals(featureID)) {
			this.source = (ObjectVariable) value;
		} else if (ModelPackage.LINK_TEMPLATE_TARGET.equals(featureID)) {
			this.target = (ObjectVariable) value;
		} else
			super.dynamicSet(featureID, value);
	}

}
